/*
 * AY 2014/15 Semester 1 IS2103 Assignment Part2
 * Matric. No.:    A0102330H
 * Name:           Cui Lin
 */
package ejb;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author cuilin
 */
@Stateless
public class MRSAdminManagerBean implements MRSAdminManagerBeanRemote {

    @PersistenceContext
    EntityManager em;
    private ModuleEntity moduleEntity;
    private LecturerEntity lecturerEntity;
    private SynopsisEntity synopsisEntity;
    private StudentEntity studentEntity;
    private TutorialEntity tutorialEntity;
    private Set<TutorialEntity> tutorials;
    private TutorEntity tutorEntity;

    public MRSAdminManagerBean() {
    }

    @Override
    public void addModule(String moduleCode, String moduleTitle, String t, String venue) {
        moduleEntity = new ModuleEntity();
        moduleEntity.create(moduleCode, moduleTitle, t, venue);
    }

    @Override
    public Long persistModule() {
        moduleEntity.setLecturer(lecturerEntity);
        moduleEntity.setSynopsis(synopsisEntity);
        em.persist(moduleEntity);
        em.flush();
        return moduleEntity.getId();
    }

    @Override
    public boolean isExistModule(String moduleCode) {
        return null != findModuleEntity(moduleCode);
    }

    @Override
    public Long findModuleId(String moduleCode) {
        return findModuleEntity(moduleCode).getId();
    }

    @Override
    public void deleteModule(Long id) {
        //TODO: disassociated from lecturer
        //TODO: associated synopsis and tutorials are deleted
        //Delete module
        ModuleEntity module = em.find(ModuleEntity.class, id);
        em.remove(module);
        em.flush();

    }

    @Override
    public List viewModuleDetails(String moduleCode) {
        try {
            ArrayList entity = new ArrayList();

            ModuleEntity module = findModuleEntity(moduleCode);
            if (null != module) {
                entity.add(module.getModuleTitle());
                entity.add(module.getT());
                entity.add(module.getVenue());
                entity.add(module.getLecturer().getName());
                entity.add(module.getSynopsis().getContent());
                //get list of student(name,matric,email)
                ArrayList studentlist = new ArrayList();
                if (module.getStudents() != null && !module.getStudents().isEmpty()) {
                    Set<StudentEntity> students = module.getStudents();
                    System.out.println("LOG students.size() = " + students.size());
                    for (StudentEntity student : students) {
                        ArrayList b = new ArrayList();
                        b.add(student.getName());
                        b.add(student.getMatricNumber());
                        b.add(student.getEmail());
                        studentlist.add(b);
                    }
                }
                entity.add(studentlist);
            }
            return entity;
        } catch (Exception ex) {
            System.out.println("MRSManagerBean: viewModuleDetails(): Caught an unexpected exception: " + ex.toString());
            return null;
        }
    }

    @Override
    public void addLecturer(String staffNumber, String title, String name, String email, String office) {
        lecturerEntity = new LecturerEntity();
        lecturerEntity.create(staffNumber, title, name, email, office);
    }

    @Override
    public Long persistLecturer() {
        em.persist(lecturerEntity);
        em.flush();
        return lecturerEntity.getId();
    }

    @Override
    public boolean isExistLecturer(String staffNumber) {
        List list = findLecturers(staffNumber);
        return (null != list && !list.isEmpty());
    }

    @Override
    public List findLecturers(String staffNumber) {
        Query q = em.createQuery("SELECT l.id FROM LecturerEntity l WHERE l.staffNumber='" + staffNumber + "'");
        return q.getResultList();
    }

    @Override
    public void deleteLecturer(Long id) {
        try {
            LecturerEntity lecturer = em.find(LecturerEntity.class, id);
            em.remove(lecturer);
            em.flush();
        } catch (EntityNotFoundException enfe) {
            System.out.println("\nEntity Not Found error: " + enfe.getMessage());
        }
    }

    @Override
    public Long findLecturerId(String staffNumber) {
        LecturerEntity l;
        Query q = em.createQuery("SELECT l FROM LecturerEntity l WHERE l.staffNumber='" + staffNumber + "'");
        l = (LecturerEntity) q.getSingleResult();
        Long id = l.getId();
        return id;
    }

    @Override
    public boolean isAsscociateLecturer(Long lecturerId) {
        Query q = em.createQuery("SELECT m FROM ModuleEntity m WHERE m.lecturer.id=:lid");
        q.setParameter("lid", lecturerId);
        List list = q.getResultList();
        return (null != list && !list.isEmpty());
    }

    @Override
    public void associateModuleLecturer(Long lecturerId) {
        lecturerEntity = em.find(LecturerEntity.class, lecturerId);
        moduleEntity.setLecturer(lecturerEntity);
        em.persist(moduleEntity);
        em.flush();
    }

    @Override
    public void addSynopsis(String content) {
        synopsisEntity = new SynopsisEntity();
        synopsisEntity.create(content);
    }

    @Override
    public void addStudent(String matricNumber, String name, String password, String email) {
        studentEntity = new StudentEntity();
        studentEntity.create(matricNumber, name, password, email);
        em.persist(studentEntity);
        em.flush();
    }

    @Override
    public void updateStudent(Long id, String password, String email) {
        studentEntity = em.find(StudentEntity.class, id);
        if (null != password && !"".equals(password)) {
            studentEntity.setPassword(password);
        }
        if (null != email && !"".equals(email)) {
            studentEntity.setEmail(email);
        }
        em.persist(studentEntity);
        em.flush();
    }

    @Override
    public boolean isExistStudent(String matricNumber) {
        List list = findStudent(matricNumber);
        return (null != list && !list.isEmpty());
    }

    @Override
    public void deleteStudent(Long id) {
        try {
            StudentEntity student = em.find(StudentEntity.class, id);
            em.remove(student);
            em.flush();
        } catch (EntityNotFoundException enfe) {
            System.out.println("\nEntity Not Found error: " + enfe.getMessage());
        }
    }

    @Override
    public Long findStudentId(String matricNumber) {
        return (Long) findStudent(matricNumber).get(0);
    }

    
    @Override
    public List findStudent(String matricNumber) {
        List student;
        Query q = em.createQuery("SELECT s FROM StudentEntity s WHERE s.matricNumber='" + matricNumber + "'");
        List students = q.getResultList();
        if (null == students || students.isEmpty()) {
            return null;
        }

        StudentEntity s = (StudentEntity) q.getSingleResult();
        student = new ArrayList();
        student.add(s.getId());
        student.add(s.getMatricNumber());
        student.add(s.getPassword());
        student.add(s.getEmail());
        
        return student;
    }
    
    @Override
    public List findStudentModules(Long id) {
        
        Query qm = em.createQuery("SELECT s.modules FROM StudentEntity s WHERE s.id=" + id);
        List<ModuleEntity> modules = null;
        if(null != qm.getResultList()){
            modules = (List<ModuleEntity>)qm.getResultList();
        }

        Query qt = em.createQuery("SELECT s.tutorials FROM StudentEntity s WHERE s.id=" + id);
        List<TutorialEntity> mytuts= null;
        if(null != qt.getResultList()){
            mytuts = (List<TutorialEntity>)qt.getResultList();
        }

        List mymodules = new ArrayList();
        if (null != modules && !modules.isEmpty()) {
            for (ModuleEntity mentity : modules) {
                List m = new ArrayList();
                m.add(mentity.getId());
                m.add(mentity.getT());
                m.add(mentity.getModuleCode());
                m.add(mentity.getModuleTitle());
                m.add(mentity.getLecturer().getName());
                m.add(mentity.getVenue());

                List mytutorials = new ArrayList();
                Set<TutorialEntity> mtutorials = mentity.getTutorials();
                if (null != mytuts && !mytuts.isEmpty() && null != mtutorials && !mtutorials.isEmpty()) {
                    for (TutorialEntity tut : mtutorials) {
                        if (mytuts.contains(tut)) {
                            List t = new ArrayList();
                            t.add(tut.getId());
                            t.add(tut.getT());
                            t.add(tut.getGroupNumber());
                            t.add(tut.getTutor().getName());
                            t.add(tut.getVenue());
                            mytutorials.add(t);
                        }
                    }
                }
                m.add(mytutorials);
                mymodules.add(m);
            }
        }

        return mymodules;
    }

    @Override
    public void assignStudentModule(Long studentId, Long moduleId) {
        studentEntity = em.find(StudentEntity.class, studentId);
        moduleEntity = em.find(ModuleEntity.class, moduleId);

        moduleEntity.addStudentEntity(studentEntity);
        em.persist(moduleEntity);
        em.flush();
    }

    @Override
    public boolean isAssociateSM(Long studentId) {
        Query q = em.createQuery("SELECT sm FROM STUDENT_MODULE sm WHERE sm.students_id='" + studentId + "'");
        List list = q.getResultList();
        return (null != list && !list.isEmpty());
    }

    
    
    @Override
    public List<List> viewAppeals() {
        try {
            Query q = em.createQuery("SELECT ae FROM AppealEntity ae");
            List<List> appeals = new ArrayList<List>();

            List<AppealEntity> results = (List<AppealEntity>) q.getResultList();
            for (AppealEntity appeal : results) {
                ArrayList entity = new ArrayList();
                entity.add(appeal.getId());
                entity.add(appeal.getT());
                entity.add(appeal.getContent());
                entity.add(appeal.getStatus());
                entity.add(appeal.getComment());
                appeals.add(entity);
            }
            return appeals;
        } catch (Exception ex) {
            System.out.println("MRSManagerBean: viewAppeals(): Caught an unexpected exception: " + ex.toString());
            return null;
        }
    }

    @Override
    public void addTutorial(String groupNumber, String t, String venue, String moduleCode) {
        tutorialEntity = new TutorialEntity();
        tutorialEntity.create(groupNumber, t, venue);

        moduleEntity = findModuleEntity(moduleCode);
        tutorials = moduleEntity.getTutorials();
        if (null == tutorials) {
            tutorials = new HashSet<TutorialEntity>();
        }
        tutorials.add(tutorialEntity);
        moduleEntity.setTutorials(tutorials);
        em.persist(moduleEntity);
        em.flush();
    }

    @Override
    public boolean isExistTutorial(String moduleCode, String groupNumber) {
        Query q = em.createQuery("SELECT m.tutorials FROM ModuleEntity m WHERE m.moduleCode='" + moduleCode + "'");
        List<TutorialEntity> tutorialGroups = q.getResultList();
        int size = tutorialGroups.size();
        for (int i = 0; i < size; i++) {
            if (tutorialGroups.get(i).getGroupNumber().equalsIgnoreCase(groupNumber)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void deleteTutorial(String moduleCode, String groupNumber) {
        Query q = em.createQuery("SELECT m.tutorials FROM ModuleEntity m WHERE m.moduleCode='" + moduleCode + "'");
        List<TutorialEntity> tutorialGroups = q.getResultList();
        int size = tutorialGroups.size();
        for (int i = 0; i < size; i++) {
            if (tutorialGroups.get(i).getGroupNumber().equalsIgnoreCase(groupNumber)) {
                em.remove(tutorialGroups.get(i));
                em.flush();
            }
        }
    }

    @Override
    public List<List> viewTutorialDetails(String moduleCode) {
        List<List> tutorialList = new ArrayList<List>();
        moduleEntity = findModuleEntity(moduleCode);
        if (null == moduleEntity || null == moduleEntity.getTutorials() || moduleEntity.getTutorials().isEmpty()) {
        } else {
            Set<TutorialEntity> results = (Set<TutorialEntity>) moduleEntity.getTutorials();
            for (TutorialEntity tutorial : results) {
                ArrayList tutor = new ArrayList();
                tutor.add(tutorial.getGroupNumber());
                tutor.add(tutorial.getT());
                tutor.add(tutorial.getVenue());
                tutor.add(tutorial.getTutor().getName());
                //get tutor and registered students
                ArrayList students = new ArrayList();
                Set<StudentEntity> studentEntitySet = (Set<StudentEntity>) tutorial.getStudents();
                if (null != studentEntitySet && !studentEntitySet.isEmpty()) {
                    for (StudentEntity student : studentEntitySet) {
                        ArrayList b = new ArrayList();
                        b.add(student.getName());
                        b.add(student.getMatricNumber());
                        b.add(student.getEmail());
                        students.add(b);
                    }
                }
                tutor.add(students);
                tutorialList.add(tutor);
            }
        }

        return tutorialList;
    }

    @Override
    public Long findTutorialId(String moduleCode, String groupNumber) {
        Query q = em.createQuery("SELECT m.tutorials FROM ModuleEntity m WHERE m.moduleCode='" + moduleCode + "'");
        List<TutorialEntity> tutorialGroups = q.getResultList();
        int size = tutorialGroups.size();
        for (int i = 0; i < size; i++) {
            if (tutorialGroups.get(i).getGroupNumber().equalsIgnoreCase(groupNumber)) {
                return tutorialGroups.get(i).getId();
            }
        }
        return null;
    }

    @Override
    public void assignStudentTutorial(Long studentId, Long tutorialId) {
        studentEntity = em.find(StudentEntity.class, studentId);
        tutorialEntity = em.find(TutorialEntity.class, tutorialId);

        tutorialEntity.addStudentEntity(studentEntity);
        em.persist(tutorialEntity);
        em.flush();
    }

    @Override
    public void addTutor(String staffNumber, String name, String email) {
        tutorEntity = new TutorEntity();
        tutorEntity.create(staffNumber, name, email);
        em.persist(tutorEntity);
    }

    @Override
    public void deleteTutor(String staffNumber) {
        TutorEntity t = findTutor(staffNumber);
        em.remove(t);
        em.flush();
    }

    @Override
    public boolean isExistTutor(String staffNumber) {
        TutorEntity tutor = findTutor(staffNumber);
        return null != tutor;
    }

    @Override
    public Long findTutorId(String staffNumber) {
        return findTutor(staffNumber).getId();
    }

    @Override
    public void associateTutorTutorial(Long tutorId, Long tutorialId) {
        tutorialEntity = (TutorialEntity) em.find(TutorialEntity.class, tutorialId);
        tutorEntity = (TutorEntity) em.find(TutorEntity.class, tutorId);
        tutorialEntity.setTutor(tutorEntity);
        em.persist(tutorialEntity);
        em.flush();
    }

    private TutorEntity findTutor(String staffNumber) {
        Query q = em.createQuery("SELECT t FROM TutorEntity t WHERE t.staffNumber='" + staffNumber + "'");
        List result = q.getResultList();
        if (null == result || result.isEmpty()) {
            return null;
        }
        return (TutorEntity) result.get(0);
    }

    private ModuleEntity findModuleEntity(String moduleCode) {
        List result = em.createQuery("SELECT m FROM ModuleEntity m WHERE m.moduleCode='" + moduleCode + "'").getResultList();
        if (null == result || result.isEmpty()) {
            return null;
        }
        return (ModuleEntity) result.get(0);
    }

    @Override
    public List findModuleEntities(String moduleCode, String moduleTitle) {
        String qSql = "SELECT m FROM ModuleEntity m ";
        if (null != moduleCode && !"".equals(moduleCode)) {
            qSql += "WHERE m.moduleCode='" + moduleCode + "'";

        } else if (null != moduleTitle && !"".equals(moduleTitle)) {
            qSql += "WHERE m.moduleTitle LIKE '%" + moduleTitle + "%'";
        }
        //m.moduleCode='" + moduleCode + "'");
        Query q = em.createQuery(qSql);
        List list = q.getResultList();
        if (null != list && !list.isEmpty()) {
            List modules = new ArrayList();
            List<ModuleEntity> ms = (List<ModuleEntity>) list;
            for (ModuleEntity m : ms) {
                List entity = new ArrayList();
                entity.add(m.getId());
                entity.add(m.getModuleCode());
                entity.add(m.getModuleTitle());
                entity.add(m.getSynopsis().getContent());
                entity.add(m.getLecturer().getName());
                entity.add(m.getT());
                entity.add(m.getVenue());
                //get list of student(name,matric,email)
                ArrayList tutlist = new ArrayList();
                if (m.getTutorials() != null && !m.getTutorials().isEmpty()) {
                    Set<TutorialEntity> tuts = m.getTutorials();
                    System.out.println("LOG getTutorials().size() = " + tuts.size());
                    for (TutorialEntity tut : tuts) {
                        ArrayList t = new ArrayList();
                        t.add(tut.getId());
                        t.add(tut.getGroupNumber());
                        t.add(tut.getTutor().getName());
                        t.add(tut.getT());
                        t.add(tut.getVenue());
                        tutlist.add(t);
                    }
                }
                entity.add(tutlist);
                modules.add(entity);
            }
            return modules;
        }
        return null;
    }

    
}
